﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace CommonTypes.Client
{
    [Serializable]
    public enum ReservationState {INITIATED, SUCCEEDED, CANCELED}

    [Serializable]
    public class Reservation
    {
        private String _initiatorId;
        private long _ticketNumber;
        private ArrayList _reservationSlots;
        private ArrayList _invitedClients;
        private DateTime _reservationTimestamp;
        private String _description;
        private ReservationState _reservationState;
        private Object _lockingObject;

        public Reservation(String initiatorId, long ticketNumber, ArrayList reservationSlots, ArrayList invitedClients, String description)
        {
            _initiatorId = initiatorId;
            _ticketNumber = ticketNumber;
            _reservationSlots = reservationSlots;
            _invitedClients = invitedClients;
            _reservationTimestamp = DateTime.Now;
            _description = description;
            _reservationState = ReservationState.INITIATED;
            _lockingObject = new Object();
        }

        public String InitiatorId
        {
            get { return _initiatorId; }
            set { _initiatorId = value; }
        }

        public long TicketNumber
        {
            get { lock (_lockingObject) {return _ticketNumber; }}
            set { lock (_lockingObject) { _ticketNumber = value; } }
        }

        public ArrayList ReservationSlots
        {
            get { return _reservationSlots; }
            set { _reservationSlots = value; }
        }

        public ArrayList InvitedClients
        {
            get { return _invitedClients; }
            set { _invitedClients = value; }
        }

        public DateTime ReservationTimestamp
        {
            get { return _reservationTimestamp; }
            set { _reservationTimestamp = value; }
        }

        public String Description
        {
            get { return _description; }
            set { _description = value; }
        }

        public ReservationState ReservationState
        {
            get { lock (_lockingObject) { return _reservationState; } }
            set { lock (_lockingObject) { _reservationState = value; } }
        }

        public bool MergeClientSlots(ArrayList availableSlots)
        {
            if (availableSlots.Count == 0)
            {
                ReservationState = ReservationState.CANCELED;
                return false;
            }

            bool found, foundAny = false;
            long smallerAvailableSlot = 0;

            //Descarta todos os slots da reserva não disponiveis
            foreach (ReservationSlot reservationSlot in ReservationSlots)
            {
                found = false;

                if (smallerAvailableSlot <= reservationSlot.SlotNumber)
                {
                    foreach (long availableSlot in availableSlots)
                    {
                        if (reservationSlot.SlotNumber == availableSlot)
                        {
                            found = true;
                            foundAny = true;
                            availableSlots.Remove(availableSlot);

                            if (availableSlots.Count > 0)
                                smallerAvailableSlot = (long)availableSlots[0];

                            break;
                        }
                    }
                }

                if (!found)
                {
                    reservationSlot.SlotState = ReservationSlotState.ABORTED;
                }
            }

            return foundAny;
        }

        public ReservationSlot GetReservationSlot(int index)
        {
            ReservationSlot slot = (ReservationSlot)_reservationSlots[index];
            return slot;
        }

        public override String ToString()
        {
            StringBuilder ret = new StringBuilder();
            ret.AppendFormat("Ticket {0}, Name: {1}, Initiated by {2}", _ticketNumber, _description, _initiatorId);
            return ret.ToString();
        }
    }    
}
